package com.healthcare.cameraview.service;

import com.healthcare.cameraview.ws.VideoWebSocketHandler;
import com.healthcare.cameraview.ws.QwenHttpClient;
import com.healthcare.cameraview.config.ApiConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import jakarta.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Random;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

@Service
public class FrameProcessorOptimized {
    private static final Logger logger = LoggerFactory.getLogger(FrameProcessorOptimized.class);

    @Autowired
    private ApiConfig apiConfig;
    
    private QwenHttpClient qwenClient;    // Windows 下 FFmpeg 访问默认摄像头的命令
    private static final String[] CMD = {
            "ffmpeg",
            "-f", "dshow",
            "-list_devices", "true", 
            "-i", "dummy"
    };

    // 动态摄像头命令 - 根据配置自动选择
    private String[] cameraCmd;
    private String cameraSource;

    private final AtomicBoolean useRealCamera = new AtomicBoolean(true);
    private final AtomicBoolean isPaused = new AtomicBoolean(false);
    private final Random random = new Random();    private final AtomicLong lastAnalysisTime = new AtomicLong(0);
    private static final long ANALYSIS_INTERVAL = 1000; // 1秒分析一次

    @PostConstruct
    public void startProcessing() {
        try {
            logger.info("开始初始化优化版摄像头处理服务...");
            
            // 初始化通义千问客户端
            if (apiConfig.getApiKey() != null && !apiConfig.getApiKey().isEmpty()) {
                qwenClient = new QwenHttpClient(apiConfig.getApiKey());
                logger.info("通义千问HTTP客户端初始化成功");
            } else {
                logger.warn("API密钥未配置，AI分析功能将被禁用");
            }
            
            // 配置摄像头命令
            configureCameraCommand();
            
            // 先尝试获取摄像头列表（仅对设备摄像头）
            if ("device".equals(apiConfig.getCameraSourceType()) || "auto".equals(apiConfig.getCameraSourceType())) {
                listCameraDevices();
            }

            // 启动摄像头捕获或模拟
            if (useRealCamera.get()) {
                startRealCameraCapture();
            } else {
                logger.info("切换到模拟摄像头模式");
                startMockCameraSimulation();
            }
        } catch (Exception e) {
            logger.error("初始化失败: {}", e.getMessage(), e);
            useRealCamera.set(false);
            startMockCameraSimulation();
        }
    }

    private void configureCameraCommand() {
        String sourceType = apiConfig.getCameraSourceType();
        cameraSource = sourceType;
        
        logger.info("摄像头配置 - 类型: {}, URL: {}, 设备: {}", 
                sourceType, apiConfig.getCameraUrl(), apiConfig.getCameraDeviceName());
        
        switch (sourceType.toLowerCase()) {
            case "http":
                configureHttpCamera();
                break;
            case "rtsp":
                configureRtspCamera();
                break;
            case "device":
                configureDeviceCamera();
                break;
            case "auto":
            default:
                configureAutoCamera();
                break;
        }
    }
    
    private void configureHttpCamera() {
        if (apiConfig.getCameraUrl().isEmpty()) {
            logger.error("HTTP摄像头URL未配置，切换到模拟模式");
            useRealCamera.set(false);
            return;
        }
        
        logger.info("配置HTTP摄像头: {}", apiConfig.getCameraUrl());
        cameraCmd = new String[]{
            "ffmpeg",
            "-i", apiConfig.getCameraUrl(),
            "-r", String.valueOf(apiConfig.getCameraFps()),
            "-s", apiConfig.getCameraWidth() + "x" + apiConfig.getCameraHeight(),
            "-vcodec", "mjpeg",
            "-q:v", "3",
            "-f", "image2pipe",
            "-"
        };
    }
    
    private void configureRtspCamera() {
        if (apiConfig.getCameraUrl().isEmpty()) {
            logger.error("RTSP摄像头URL未配置，切换到模拟模式");
            useRealCamera.set(false);
            return;
        }
        
        logger.info("配置RTSP摄像头: {}", apiConfig.getCameraUrl());
        cameraCmd = new String[]{
            "ffmpeg",
            "-rtsp_transport", "tcp",
            "-i", apiConfig.getCameraUrl(),
            "-r", String.valueOf(apiConfig.getCameraFps()),
            "-s", apiConfig.getCameraWidth() + "x" + apiConfig.getCameraHeight(),
            "-vcodec", "mjpeg",
            "-q:v", "3",
            "-f", "image2pipe",
            "-"
        };
    }
    
    private void configureDeviceCamera() {
        logger.info("配置设备摄像头: {}", apiConfig.getCameraDeviceName());
        cameraCmd = new String[]{
            "ffmpeg",
            "-f", "dshow",
            "-i", "video=" + apiConfig.getCameraDeviceName(),
            "-r", String.valueOf(apiConfig.getCameraFps()),
            "-s", apiConfig.getCameraWidth() + "x" + apiConfig.getCameraHeight(),
            "-vcodec", "mjpeg",
            "-q:v", "3",
            "-f", "image2pipe",
            "-"
        };
    }
    
    private void configureAutoCamera() {
        // 自动模式：优先使用HTTP URL，如果没有则使用设备摄像头
        if (!apiConfig.getCameraUrl().isEmpty()) {
            if (apiConfig.getCameraUrl().startsWith("rtsp://")) {
                logger.info("自动检测到RTSP地址，使用RTSP模式");
                configureRtspCamera();
            } else {
                logger.info("自动检测到HTTP地址，使用HTTP模式");
                configureHttpCamera();
            }
        } else {
            logger.info("未配置URL，使用设备摄像头模式");
            configureDeviceCamera();
        }
    }    private void startRealCameraCapture() {
        logger.info("正在启动摄像头捕获 ({}FPS显示 + 1FPS AI分析) - 源: {}", 
                apiConfig.getCameraFps(), cameraSource);
        logger.info("FFmpeg命令: {}", String.join(" ", cameraCmd));
        
        new Thread(() -> {
            try {
                ProcessBuilder builder = new ProcessBuilder(cameraCmd);
                builder.redirectErrorStream(true);
                Process process = builder.start();

                // 创建错误流读取线程
                Thread errorThread = new Thread(() -> {
                    try (BufferedReader reader = new BufferedReader(
                            new InputStreamReader(process.getErrorStream()))) {
                        String line;
                        while ((line = reader.readLine()) != null) {
                            logger.debug("FFmpeg输出: {}", line);
                        }
                    } catch (IOException e) {
                        logger.error("读取FFmpeg错误流失败: {}", e.getMessage());
                    }
                });
                errorThread.start();

                InputStream inputStream = process.getInputStream();
                ByteArrayOutputStream frameBuffer = new ByteArrayOutputStream();

                boolean capturing = false;
                int prev = -1;
                int curr;
                int frameCount = 0;
                int displayFrames = 0;
                int analysisFrames = 0;

                while ((curr = inputStream.read()) != -1) {
                    if (prev == 0xFF && curr == 0xD8) {
                        frameBuffer.reset();
                        frameBuffer.write(0xFF);
                        capturing = true;
                    }

                    if (capturing) {
                        frameBuffer.write(curr);
                    }                    if (prev == 0xFF && curr == 0xD9) {
                        capturing = false;
                        byte[] imageBytes = frameBuffer.toByteArray();
                        frameCount++;
                        
                        try {
                            // 检查是否暂停
                            if (isPaused.get()) {
                                // 暂停时发送暂停状态消息
                                String pausedPayload = "{\"type\":\"status\",\"message\":\"摄像头已暂停\"}";
                                VideoWebSocketHandler.broadcast(pausedPayload);
                                Thread.sleep(100); // 暂停时降低CPU使用率
                                continue;
                            }
                            
                            // 所有帧都用于显示（30FPS）
                            String base64Image = Base64.encodeBase64String(imageBytes);
                            String payload = String.format(
                                "{\"image\":\"data:image/jpeg;base64,%s\"}", 
                                base64Image
                            );
                            VideoWebSocketHandler.broadcast(payload);
                            displayFrames++;
                              // 每30帧打印一次显示统计
                            if (displayFrames % 30 == 0) {
                                logger.info("显示帧统计: {} 帧 ({}FPS) - 源: {}", 
                                        displayFrames, apiConfig.getCameraFps(), cameraSource);
                            }

                            // 每秒选择一帧进行AI分析
                            long currentTime = System.currentTimeMillis();                            if (currentTime - lastAnalysisTime.get() >= ANALYSIS_INTERVAL) {
                                lastAnalysisTime.set(currentTime);
                                final int currentAnalysisFrame = analysisFrames + 1;
                                analysisFrames = currentAnalysisFrame;
                                
                                // 在单独线程中进行AI分析，不阻塞视频流
                                byte[] analysisImageBytes = imageBytes.clone();
                                new Thread(() -> {
                                    try {
                                        analyzeFrame(analysisImageBytes, currentAnalysisFrame);
                                    } catch (Exception e) {
                                        logger.error("AI分析失败: {}", e.getMessage());
                                    }
                                }).start();
                            }

                        } catch (Exception e) {
                            logger.error("处理图像帧失败: {}", e.getMessage());
                        }
                    }

                    prev = curr;
                }

                process.waitFor();
                logger.warn("摄像头进程已退出，切换到模拟模式");
                useRealCamera.set(false);
                startMockCameraSimulation();
            } catch (Exception e) {
                logger.error("摄像头捕获失败: {}", e.getMessage(), e);
                useRealCamera.set(false);
                startMockCameraSimulation();
            }
        }).start();
    }

    private void analyzeFrame(byte[] imageBytes, int frameNumber) {
        try {
            if (qwenClient != null) {
                logger.info("正在分析第 {} 帧 (大小: {} 字节)...", frameNumber, imageBytes.length);
                
                // 转换为base64
                String base64Image = Base64.encodeBase64String(imageBytes);                // 调用通义千问进行康养照护异常行为预测分析
                String prompt = "你是一个康养照护情境中的异常行为预测发现系统，请你根据传入的数据预测异常行为。" +
                              "请你仅返回如下格式的JSON数据：" +
                              "{\"level\": 3, \"reason\": \"人物有明显的上肢下落倾向\", \"predict\": \"跌倒\"}" +
                              "其中level中的1-3表示异常行为的严重等级，reason是即将发生异常行为的原因，predict是预测即将发生的异常行为";
                qwenClient.analyzeImage(base64Image, prompt);
                  } else {
                // 只打印到控制台
                logger.warn("AI分析服务未配置 (帧: {})", frameNumber);
            }        } catch (Exception e) {
            logger.error("❌ 分析第 {} 帧失败: {}", frameNumber, e.getMessage());
        }
    }    private void startMockCameraSimulation() {
        logger.info("启动模拟摄像头 ({}FPS显示 + 1FPS AI分析)...", apiConfig.getCameraFps());
        new Thread(() -> {
            try {
                int frameCount = 0;
                int analysisFrames = 0;
                int displayInterval = 1000 / apiConfig.getCameraFps(); // 计算帧间隔
                  while (true) {
                    // 检查是否暂停
                    if (isPaused.get()) {
                        // 暂停时发送暂停状态消息
                        String pausedPayload = "{\"type\":\"status\",\"message\":\"模拟摄像头已暂停\"}";
                        VideoWebSocketHandler.broadcast(pausedPayload);
                        Thread.sleep(500); // 暂停时降低检查频率
                        continue;
                    }
                    
                    // 生成随机彩色图像
                    BufferedImage image = generateRandomImage(
                            apiConfig.getCameraWidth(), 
                            apiConfig.getCameraHeight()
                    );
                    
                    // 转换为字节数组
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ImageIO.write(image, "jpg", baos);
                    byte[] imageBytes = baos.toByteArray();
                    frameCount++;
                      // 所有帧都用于显示
                    String base64Image = Base64.encodeBase64String(imageBytes);
                    String payload = String.format(
                        "{\"image\":\"data:image/jpeg;base64,%s\"}", 
                        base64Image
                    );
                    VideoWebSocketHandler.broadcast(payload);                    // 每FPS帧进行一次AI分析
                    if (frameCount % apiConfig.getCameraFps() == 0) {
                        analysisFrames++;                        String result = simulateModel(imageBytes, analysisFrames);
                        
                        // 打印到控制台
                        logger.info("🤖 模拟康养异常行为预测第 {} 帧: {}", analysisFrames, result);
                        
                        // 尝试解析并发送结构化结果
                        try {
                            ObjectMapper objectMapper = new ObjectMapper();
                            @SuppressWarnings("unchecked")
                            Map<String, Object> predictionData = objectMapper.readValue(result, Map.class);
                            
                            // 发送结构化的异常行为预测结果到前端
                            String analysisPayload = String.format(
                                "{\"type\":\"analysis\",\"level\":%s,\"reason\":\"%s\",\"predict\":\"%s\",\"timestamp\":%d}", 
                                predictionData.get("level"),
                                String.valueOf(predictionData.get("reason")).replace("\"", "\\\""),
                                String.valueOf(predictionData.get("predict")).replace("\"", "\\\""),
                                System.currentTimeMillis()
                            );
                            VideoWebSocketHandler.broadcast(analysisPayload);
                        } catch (Exception e) {
                            logger.error("解析模拟预测结果失败: {}", e.getMessage());
                            // 发送原始结果作为fallback
                            String analysisPayload = String.format(
                                "{\"type\":\"analysis\",\"result\":\"%s\",\"timestamp\":%d}", 
                                result.replace("\"", "\\\""), 
                                System.currentTimeMillis()
                            );
                            VideoWebSocketHandler.broadcast(analysisPayload);
                        }
                    }
                    
                    // 动态帧率间隔
                    Thread.sleep(displayInterval);
                }
            } catch (Exception e) {
                logger.error("模拟摄像头失败: {}", e.getMessage());
            }
        }).start();
    }

    private BufferedImage generateRandomImage(int width, int height) {
        // 创建彩色图像
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = image.createGraphics();
        
        // 填充背景
        g2d.setColor(new Color(random.nextInt(100), random.nextInt(100), random.nextInt(100)));
        g2d.fillRect(0, 0, width, height);
        
        // 添加一些随机形状
        for (int i = 0; i < 10; i++) {
            g2d.setColor(new Color(
                random.nextInt(256), 
                random.nextInt(256), 
                random.nextInt(256)
            ));
            
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int size = 30 + random.nextInt(100);
            
            switch (random.nextInt(3)) {
                case 0:
                    g2d.fillOval(x, y, size, size);
                    break;
                case 1:
                    g2d.fillRect(x, y, size, size);
                    break;
                case 2:
                    int[] xPoints = new int[3];
                    int[] yPoints = new int[3];
                    for (int j = 0; j < 3; j++) {
                        xPoints[j] = x + random.nextInt(size);
                        yPoints[j] = y + random.nextInt(size);
                    }
                    g2d.fillPolygon(xPoints, yPoints, 3);
                    break;
            }
        }
          // 添加当前时间文本和帧信息
        g2d.setColor(Color.WHITE);
        g2d.setFont(new Font("Arial", Font.BOLD, 16));
        g2d.drawString(String.format("模拟摄像头 - %tc", System.currentTimeMillis()), 20, 30);
        g2d.drawString(String.format("%dFPS 实时显示", apiConfig.getCameraFps()), 20, 50);
        
        g2d.dispose();
        return image;
    }    private String simulateModel(byte[] image, int frameNumber) {
        // 模拟康养照护异常行为预测结果
        String[] predictions = {
            "{\"level\": 1, \"reason\": \"人物姿态正常，行走稳定\", \"predict\": \"正常活动\"}",
            "{\"level\": 1, \"reason\": \"正在进行日常坐立活动\", \"predict\": \"正常休息\"}",
            "{\"level\": 2, \"reason\": \"人物走路速度较慢，可能疲劳\", \"predict\": \"需要休息\"}",
            "{\"level\": 2, \"reason\": \"检测到轻微摇摆，平衡感略差\", \"predict\": \"注意平衡\"}",
            "{\"level\": 1, \"reason\": \"环境安全，人物状态良好\", \"predict\": \"继续活动\"}",
            "{\"level\": 3, \"reason\": \"人物有明显的上肢下落倾向\", \"predict\": \"跌倒风险\"}",
            "{\"level\": 2, \"reason\": \"检测到异常姿态变化\", \"predict\": \"需要关注\"}",
            "{\"level\": 1, \"reason\": \"正常的康复训练动作\", \"predict\": \"训练进行中\"}"
        };
        
        return predictions[random.nextInt(predictions.length)];
    }

    private void listCameraDevices() {
        try {
            ProcessBuilder builder = new ProcessBuilder(CMD);
            builder.redirectErrorStream(true);
            Process process = builder.start();
            process.waitFor();
            logger.info("已完成摄像头设备列表获取");
        } catch (Exception e) {
            logger.error("获取摄像头列表失败: {}", e.getMessage());
            useRealCamera.set(false);
        }
    }

    // 暂停/恢复控制方法
    public void pauseCapture() {
        isPaused.set(true);
        logger.info("摄像头捕获已暂停");
    }

    public void resumeCapture() {
        isPaused.set(false);
        logger.info("摄像头捕获已恢复");
    }

    public boolean isPaused() {
        return isPaused.get();
    }
}
